// @File  : socket.go
// @Author: JunLong.Liao&此处不应有BUG!
// @Date  : 2021/4/10
// @slogan: 又是不想写代码的一天，神兽保佑，代码无BUG！
//         ┏┓      ┏┓
//        ┏┛┻━━━━━━┛┻┓
//        ┃     ღ    ┃
//        ┃  ┳┛   ┗┳ ┃
//        ┃     ┻    ┃
//        ┗━┓      ┏━┛
//          ┃      ┗━━━┓
//          ┃ 神兽咆哮!  ┣┓
//          ┃         ┏┛
//          ┗┓┓┏━━━┳┓┏┛
//           ┃┫┫   ┃┫┫
//           ┗┻┛   ┗┻┛

package websocket

import (
	"encoding/json"
	"fmt"
	"github.com/gin-gonic/gin"
	"github.com/gorilla/websocket"
	"log"
	"net/http"
	"sync/atomic"
	"time"
)

// webSocket连接
func (manager *Manager) WsClient(ctx *gin.Context) {
	upGrader := websocket.Upgrader{
		// cross origin domain
		CheckOrigin: func(r *http.Request) bool {
			return true
		},
		// 处理 Sec-WebSocket-Protocol Header
		Subprotocols: []string{ctx.GetHeader("Sec-WebSocket-Protocol")},
	}
	conn, err := upGrader.Upgrade(ctx.Writer, ctx.Request, nil)
	if err != nil {
		log.Printf("websocket connect error: %s", ctx.Param("channel"))
		return
	}
	client := &Client{
		Id:      atomic.AddInt32(&manager.incr, 1),
		Socket:  conn,
		Message: make(chan []byte, 1024),
	}
	go client.Read(manager)
	go client.Write()
	manager.RegisterClient(client)
}

// 读取websocket发送来的数据
func (c *Client) Read(manager *Manager) {
	defer func() {
		log.Printf("close:[%s],date:%s", c.Id, time.Now())
		WebsocketManager.UnRegister <- c
	}()
	for {
		messageType, message, err := c.Socket.ReadMessage()
		if err != nil || messageType == websocket.CloseMessage {
			break
		}
		var ResponseData []byte
		ReadMessage := ReadMessageRequest{}
		if err := json.Unmarshal(message, &ReadMessage); err != nil {
			ResponseData, _ = json.Marshal(MessageResponse{Status: 201, Message: "消息发送失败", Type: 1, FromId: SystemId})
			c.Message <- ResponseData
		} else {
			acceptClient, ok := manager.IdClientMap[ReadMessage.AcceptId]
			fmt.Printf("ok:%s,acceptId:%s", ok, ReadMessage.AcceptId)
			if !ok {
				ResponseData, _ = json.Marshal(MessageResponse{Status: 201, Message: "消息发送失败,对方已离线", Type: 1, FromId: SystemId})
				c.Message <- ResponseData
			} else {
				ResponseData, _ = json.Marshal(MessageResponse{Status: 200, Message: ReadMessage.Message, Type: 1, FromId: c.Id})
				acceptClient.Message <- ResponseData
			}
		}

		fmt.Printf("[clientId:]%v,[message:]%s\n", c.Id, message)
	}

}

// 写信息，从 channel 变量 Send 中读取数据写入 websocket 连接
func (c *Client) Write() {
	defer func() {
		log.Printf("clientWrite [%s] disconnect", c.Id)
		if err := c.Socket.Close(); err != nil {
			log.Printf("clientWrite [%s] disconnect err: %s", c.Id, err)
		}
	}()
	for {
		select {
		case message, ok := <-c.Message:
			if !ok {
				_ = c.Socket.WriteMessage(websocket.CloseMessage, []byte{})
				return
			}

			err := c.Socket.WriteMessage(websocket.TextMessage, message)
			if err != nil {
				log.Printf("client [%s] writemessage err: %s", c.Id, err)
			}
		}
	}
}

// 注册用户进程
func (manager *Manager) RegisterClient(c *Client) {
	manager.Register <- c
}

// 注销用户进程
func (manager *Manager) UnRegisterClient(c *Client) {
	manager.UnRegister <- c
}

// 监听用户进程注册，用户进程注销
func (manager *Manager) Start() {
	for {
		select {
		case client := <-manager.Register:
			log.Printf("client [%s] connect", client.Id)
			/*		log.Printf("register client [%s] to group [%s]", client.Id, client.Group)
			 */
			manager.Lock.RLock()
			if _, ok := manager.IdClientMap[client.Id]; ok {
				manager.IdClientMap[client.Id].Socket.Close()
			}
			manager.IdClientMap[client.Id] = client
			ResponseData, _ := json.Marshal(MessageResponse{Status: 200, Message: fmt.Sprintf("连接成功，您的会话ID为[%v]", client.Id), Type: 1, FromId: SystemId})
			client.Message <- ResponseData
			manager.Lock.RUnlock()

		// 注销
		case client := <-manager.UnRegister:

			/*if err := client.Socket.Close(); err != nil {
				log.Printf("client [%s] disconnect err: %s", client.Id, err)
			}*/
			manager.Lock.Lock()
			delete(manager.IdClientMap, client.Id)
			// for _, group := range client.GroupList {
			// 	log.Printf("unregister client [%s] from group [%s]", client.Id, group)
			// 	if _, ok := manager.RealTimeGroup[group]; ok {
			// 		if _, ok := manager.RealTimeGroup[group][client.Id]; ok {
			// 			if len(manager.RealTimeGroup[group]) == 1 {
			// 				//log.Printf("delete empty group [%s]", client.Group)
			//
			// 				delete(manager.RealTimeGroup, group)
			// 			} else {
			// 				delete(manager.RealTimeGroup[group], client.Id)
			// 			}
			// 		}
			// 	}
			// }
			manager.Lock.Unlock()
			close(client.Message)
		}
	}
}
